/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#include "FishGroup.h"

namespace Fish3D
{
	FishGroup::FishGroup(Ogre::SceneManager* sceneMgr,Ogre::String fishGroupName,Ogre::String meshName)
		: NUM_FISH(20), NUM_FISH_WAYPOINTS(10), FISH_PATH_LENGTH(200), FISH_SCALE(4),
		_sceneMgr(sceneMgr)
	{
		_rayQuery=_sceneMgr->createRayQuery(Ogre::Ray());


		_fishNodes.resize(NUM_FISH);
		_fishAnimStates.resize(NUM_FISH);
		_fishSplines.resize(NUM_FISH);

		for (unsigned int i = 0; i < NUM_FISH; i++){
			Ogre::Entity* ent = _sceneMgr->createEntity(fishGroupName + Ogre::StringConverter::toString(i + 1), meshName);
            _entities.push_back(ent);
			_fishNodes[i] = _sceneMgr->getRootSceneNode()->createChildSceneNode();
			_fishNodes[i]->setScale(Ogre::Vector3::UNIT_SCALE * FISH_SCALE);
            _fishNodes[i]->attachObject(ent);
			
			if(ent->hasSkeleton()){
				_fishAnimStates[i] = ent->getAnimationState("swim");
				_fishAnimStates[i]->setEnabled(true);
			}else{
				_fishAnimStates[i]=0;
			}

            _fishSplines[i].setAutoCalculate(false);

            for (unsigned int j = 0; j < NUM_FISH_WAYPOINTS; j++){
				Ogre::Vector3 pos(Ogre::Math::SymmetricRandom() * 260, 40, Ogre::Math::SymmetricRandom() * 680);
				pos+=Ogre::Vector3(1500,0,1500);
				
                if (j > 0) {
					const Ogre::Vector3& lastPos = _fishSplines[i].getPoint(j - 1);
					Ogre::Vector3 delta = pos - lastPos;
					if (delta.length() > 750) pos = lastPos + delta.normalisedCopy() * 750;
                }
                _fishSplines[i].addPoint(pos);
            }

			// close the spline and calculate all the tangents at once
            _fishSplines[i].addPoint(_fishSplines[i].getPoint(0));
            _fishSplines[i].recalcTangents();
        }

		_fishAnimTime = 0;

	}

	FishGroup::~FishGroup()
	{
	}

	void FishGroup::update(float deltaT)
	{
		// update the fish spline path animations and loop as needed
		_fishAnimTime += deltaT;
		while (_fishAnimTime >= FISH_PATH_LENGTH){
			_fishAnimTime -= FISH_PATH_LENGTH;
		}

        for (unsigned int i = 0; i < NUM_FISH; i++){
			if(_fishAnimStates[i]){
				_fishAnimStates[i]->addTime(deltaT * 2);  // update fish swim animation
			}

			// set the new position based on the spline path and set the direction based on displacement
			Ogre::Vector3 lastPos = _fishNodes[i]->getPosition();
			_fishNodes[i]->setPosition(_fishSplines[i].interpolate(_fishAnimTime / FISH_PATH_LENGTH));
			keepOnGround(i);
			_fishNodes[i]->setDirection(_fishNodes[i]->getPosition() - lastPos, Ogre::Node::TS_PARENT, Ogre::Vector3::NEGATIVE_UNIT_X);
			_fishNodes[i]->setFixedYawAxis(true);
        }

		

	}

	void FishGroup::keepOnGround(int i)
	{
		Ogre::SceneNode* node=_fishNodes[i];
		_rayQuery->setRay(Ogre::Ray(node->getPosition()+Ogre::Vector3(0,-2000,0),Ogre::Vector3::UNIT_Y));
		
		Ogre::RaySceneQueryResult &result=_rayQuery->execute();
		Ogre::RaySceneQueryResult::iterator it=result.begin();
		if(it!=result.end()&&it->worldFragment){
			node->setPosition(node->getPosition().x,it->worldFragment->singleIntersection.y+10,node->getPosition().z);
		}

	}
}
